package Nonogram;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import javax.swing.JOptionPane;

/**
 * Data
 * @author Rachel Wedewer, Mollie Burkle, Kristen Nielsen
 * Date Modified: 4/30/2014
 * 
 * This is one of the four main components of Nonogram. This is executed after puzzleManager returns a string path.  
 * Data then takes that path and processes the file.  The file is processed one line at a time pulling out the 
 * puzzle title(puzzleTitle), board size(boardSize), row clues (rows), and column clues (cols). Data also verifies
 * that when a puzzle is finished that it is correct.
 */
public class Data {
	
	String puzzleTitle;
	int boardsize;
	GridArray grid;
	CluesArray rows;
	CluesArray cols;
	Nonogram controller;
	
	public Data(Nonogram nono, String puzzle) throws FileNotFoundException{
		//Read Puzzle
		FileReader fr = new FileReader(puzzle);
		BufferedReader textReader = new BufferedReader(fr);
		this.controller = nono;
		String aLine;
		int lineNum = 1;
		
		try {
			while ((aLine = textReader.readLine()) != null){
				//Get Title
				if(lineNum == 1){
					puzzleTitle = aLine;
				}
				//Get boardsize
				else if (lineNum ==2){
					boardsize = Integer.parseInt(aLine);
					setupGridAndClues(boardsize);
				}
				//Setup Row Clues
				else if (lineNum >= 4 && lineNum <= 4 + (boardsize-1)){
					try {
						rows.setClueLine(aLine, lineNum-4);
					}
					catch (InvalidCluesException e)
					{
						System.out.println(e.getMessage());
					}
				}
				//Setup Col Clues
				else if (lineNum >= (4 + boardsize+1) && lineNum <= ((4 + boardsize+1) + boardsize-1)){
					try {
						cols.setClueLine(aLine, lineNum-(4 + boardsize+1));
					}
					catch (InvalidCluesException e) {
						System.out.println(e.getMessage());
					}
				}
				lineNum++;
			}
		} catch (IOException e) {
			
			e.printStackTrace();
		}

	}

	
	//Setup the board data
	public void setupGridAndClues(int boardSize) {
		grid = new GridArray(boardSize, this);
		rows = new CluesArray(boardSize);
		cols = new CluesArray(boardSize);
	}
	
 
//Show when puzzle is completed
 	private void isPuzzleCompletePopup(boolean correct){
 		controller.updateGridGUI();
 		if(correct){
 			JOptionPane.showMessageDialog (null, ("You solved puzzle " + this.getPuzzleTitle() +"!") );
 			}
 		else{
 			JOptionPane.showMessageDialog (null, "Please review the board. Something isn't quite right yet.");
 			}
 		}

	public void checkPuzzle() {
		isPuzzleCompletePopup(checkColumns() && checkRows());
	}
	
	private boolean checkColumns() {
		int[] currentCol;
		int index;
		int count;
		// Column logic
		for (int col = 0; col < boardsize; col++) {
			currentCol = cols.getLineClues(col);
			count = 0;
			index = 0;
			for (int i = 0; i < boardsize; i++) {
				if (grid.getCellValue(i, col) == 1) {
					count++;
					if (count == currentCol[index]) {
						// Number of filled in squares matches column clue at index
						if ((i+1) != boardsize && grid.getCellValue(i+1, col) ==1 ) {
							// Filled in portion is too big
							return false;
						}
					}
					else {
						if ((i+1) == boardsize) {
							// Filled in portion is too small at the end of the column
							return false;
						}
						else if (grid.getCellValue(i+1, col) == 0) {
							// Filled in portion is too small
							return false;
						}
					}
				}
				else if (count == currentCol[index]) {
					index++;
					if (index > currentCol.length - 1)
						index = currentCol.length -1;
					count = 0;
				}

			}
		}
		return true;
	}
	
	private boolean checkRows() {
		int[] currentRow;
		int index;
		int count;
		// Row logic
		for (int row = 0; row < boardsize; row++) {
			currentRow = rows.getLineClues(row);
			count = 0;
			index = 0;
			for (int i = 0; i < boardsize; i++) {
				if (grid.getCellValue(row, i)==1) {
					count ++;
					if (count == currentRow[index]) {
						if ((i+1) != boardsize && grid.getCellValue(row, i+1) == 1) {
							// Filled in portion is too big
							return false;
						}
					}
					else {
						if ((i+1) == boardsize) {
							// Filled in portion is too small
							return false;
						}
						else if (grid.getCellValue(row, i+1) == 0) {
							// Filled in portion is too small
							return false;
						}
					}
				}
				else if (count == currentRow[index]) {
					index ++;
					if (index > currentRow.length - 1)
						index = (currentRow.length - 1);
					count = 0;
				}

			}
		}
		return true;
	}
	
	////Getters
	public String getPuzzleTitle() {
		return puzzleTitle;
	}


	public int getBoardsize() {
		return boardsize;
	}
	
	public GridArray getGrid() {
		return grid;
	}

	public CluesArray getRows() {
		return rows;
	}

	public CluesArray getCols() {
		return cols;
	}
		
}
